<html>
  <head>
    <title>页面生命周期</title>
  </head>
  <body>
    <script>
       /*
                四、页面声明周期

                        uni-app除了支持vue组件生命周期外还支持下方页面生命周期函数 ,当以组合式API使用时，
                        
                        在Vue2 和 Vue3中还是存在一些区别的。

                            (请分别参考：Vue2 组合式 API 使用文档 和 Vue3 组合式 API 使用文档。)


                            函数名             说明                                                        平台差异说明                 最低版本

                         ①、onInit          监听页面初始化，器参数同onLoad 参数，为上个页面页面传递的参数。   百度小程序
                                            参数类型为object（用于页面传参），触发时机早于onLoad 
                                                      

                         ②、onLoad          监听页面加载，该钩子被调用时，响应式数据、计算属性、方法、
                                            监听器、props、slots 已经设置完成，
                                            其参数为上个页面传递的数据，参数类型为Object

                         ③、onShow          监听页面显示，页面每次出现在屏幕上都触发，
                                            包括从下级页面点返回露出当前页面

                         ④、onReady         监听页面初次渲染完成，此时组件已经挂载完成，
                                            DOM树($el)已经可用，
                                            注意如果渲染速度快，会在页面进入动画完成前触发

                         ⑤、onHide          监听页面隐藏

                         ⑥、onUnload        监听页面卸载

                         ⑦、onResize        监听窗口尺寸变化                                           App、微信小程序、快手小程序

                         ⑧、onPullDownRefresh 监听用户下拉动作，一般用于下拉刷新，示例：                 app、H5、支付宝小程序
                                            https://zh.uniapp.dcloud.io/api/ui/pulldown.html

                         ⑨、onBackPress     监听页面返回，返回 event = {from:backbutton、navigateBack}
                                            backbutton 表示来源是左上角返回按钮或 android 返回键；
                                            navigateBack表示来源是uni.navigateBack;

                         ⑩、onReachButtom   页面滚动到底部的事件(不是 scroll-view滚到底)，
                                            常用于下拉下一页数据。具体见下方注意事项

                         ⑪、onTabItemTap    点击tab时触发，参数为Object，具体见下方注意事项              微信小程序、QQ小程序、支付宝小程序、百度小程序、H5、App、快手小程序、京东小程序

                         ⑫、ohShareAppMessage 用户点击右上角分享                                       微信小程序、QQ小程序、支付宝小程序、抖音小程序、飞书小程序、快手小程序、京东小程序

                         ⑬、onPageScroll     监听页面滚动，参数为Object                                 nvue 不支持

                         ⑭、onNavigationBarButtonTap 
                                            监听页面滚动，参数为Object                                  nvue 不支持

                         ⑮、onNavigationBarSearchInputChanged
                                            监听原生标题栏搜索输入框输入内容变化事件                      App、H5

                         ⑯、onNavigationBarSearchInputClicked                                          App、H5   
                                            监听原生标题栏搜索输入框点击事件（
                                            pages.json 中的 searchInput 配置 disabled 为 true 时才会触发）

                         ⑰、onNavigationBarSearchInputConfirmed
                                            监听原生标题栏搜索输入框搜索事件，                            App、H5 
                                            用户点击软键盘上的“搜索”按钮时触发。

                         ⑱、onShareTimeLine 监听用户点击右上角转发到朋友圈                                微信小程序

                         ⑲、onAddToFavorites 监听用户点击右上角收藏                                      微信小程序、qq小程序



                    ★、Vue2 页面及组件声明周期流程图：

                         图片连接：                         
                         https://web-ext-storage.dcloud.net.cn/doc/tutorial/uni-app-lifecycle-vue2.jpg
            

                ★、页面加载时序介绍

                                  接下来我们介绍 onLoad 、 onReady、 onShow 的先后关系，页面加载的详细流程。

                                  1、uni-app框架，首先根据pages.json的配置，创建页面

                                          所以，原生导航栏是最快显示的。页面背景色也应该在这里配置。

                                  2、根据页面tempalte 里的组件，创建dom。

                                          这里的dom创建仅包含第一批处理的静态dom。对于通过js更新data然后通过v-for在创建的的列表数据，

                                          不在第一批处理。

                                          要注意一个页面静态dom元素过多，会影响页面加载速度。在uni-app x Android 版本上，可能会阻碍页面进入

                                          的转场动画。因为此时，页面转场动画还没有启动。

                                  3、触发onLoad

                                          此时页面还未显示，没有开始进入转场动画，页面dom还不存在。

                                          所以这里不能直接操作dom（可以修改data，因为vue框架会等待DOM准备后再更新界面）；

                                          在 app-uvue 中，获取当前的activity 拿到的是老页面的activity,只能通过页面栈获取activity.

                                          onLoad比较适合的操作是： 接受上页的参数，联网获取数据，跟新data。

                                          手机都是多核的，uni.request 或云开发联网，在子线程运行，不会干扰UI线程的入场动画，并行处理可以更快的

                                          拿到数据、渲染界面。

                                          但 onLoad里不适合进行大量同步耗时运算，因为此时转场动画还没开始。

                                          尤其 uni-app x 在Android上，onLoad里的代码默认是在UI线程运行的，大量同步耗时计算很容易卡住页面动画不启动。

                                          除非开发者显式指定在其他线程运行。

                                  4、转场动画开始

                                          新页面开始进入的转场动画，动画默认耗时300ms，可以在路由API中调节时长。

                                  5、页面onReady

                                          第二步创建dom是虚拟DOM，虚拟DOM创建后需要经历一段时间，UI层才能完成了页面上真实元素的创建，
                                          
                                          即触发了onReady。

                                          onReady后，页面元素就可以自由操作了，比如 ref 获取节点。同时首批界面也渲染了。

                                          注意： onReady 和  转场动画开始、结束之间，没有必然的先后顺序，完全取决于dom的数量和复杂度。

                                          如果元素排版和渲染够快，转场动画刚开始就渲染好了；

                                          大多数情况下，转场动画走几格就看到了首批渲染内容；

                                          如果元素排版和渲染过慢，转场动画结束都没有内容，就会造成拍屏。

                                          http请求进程从onLoad起就再异步获取数据更新data，如果服务器速度够快，第二批数据也可能在转场动画结束前渲染。

                                    6、转场动画结束

                                          再次强调， onReady事件触发 和 转场动画结束 的先后顺序不确定，

                                          主要是你的渲染什么时候完成，完成的快，就是先触发onReady事件，从此可以错作dom

                                          如果dom渲染的很慢，那就是转场动画先结束，但此时还没完成渲染，页面还是没有展示的，所以就白屏了。

                          
                  ★、页面加载常见问题

                            了解了页面加载的时序原理，我们就知道如何避免页面加载常见的问题：

                                1、优化白屏的方法：

                                      ①、页面dom太多，注意有的组件写的不好，回拖累整体页面。 uni-app x里减少了DOM的策略

                                              详见： https://doc.dcloud.net.cn/uni-app-x/performance.html

                                      ②、http请求不要在onReady里进行，那样太慢了，在 onLoad里早点联网

                                      ③、在pages.json 里配置原生导航栏和背景色

                                      ④、有的页面 template 内容非常少，整个也就是一个需要请求加载的列表，这样会

                                         造成首批 dom  飞快渲染了，但页面其实还是白的，联网后才能显示文字和图片。

                                         此时，需要在 template 里做一些简单站位组件，比如 loading 组件、骨架屏，让本地先显示一些内容。

                                2、卡住动画不启动的原因：

                                      ①、页面dom太多了，注意有的组件写的不好，会拖累整体页面。

                                              uni-app x 减少dom数量的策略

                                      ②、onLoad里执行了比较耗时的同步计算


                  ★、onShow 和 onHide

                              注意页面显示，是一个会重复触发的事件。

                              a页面刚刚进入，会触发a页面的onShow.

                              当 a 跳转到 b页面时， a 会触发 onHide, 而b页面会触发 onShow.

                              当b页面被关闭时，b页面会触发 onUnload,此时 a 页面再显示，会再次触发 onShow.

                              在 tabbar 页面（指pages.json里配置的 tabbar）,不同tab页面互相切换时，会触发各自的onShow 和onHide

                  ★、onInit

                              注意

                                  仅仅百度小程序基础库 3.260以上支持 onInit生命周期

                                  其他版本或平台可以同时使用　onLoad 生命周期进行兼容，注意避免重复执行相同逻辑

                                  不依赖页面传参的逻辑可以直接使用 created 生命周期替代。


                  ★、onLoad

                              注意

                                  uni-app x android 平台，如需获取activity实例，此时当前页面的 activity实例并未创建完成，

                                  或获取到上一个页面的 activity 实例（首页会获取应用默认的 activity实例）

                                  如需获取当前页面的 activity实例，应在 onShow 或 onReady 生命周期中获取。

                  ★、onReachBottom

                                可在 pages.json 里定义具体页面底部的触发距离 onReachBottomDistance,

                                比如设为50，那么滚动页面到距离底部50px时，就会触发 onReachBottom事件。

                                如使用 scroll-view 导致页面没有关东，则触底事件不会被触发。

                                scroll-view 滚动到底部的事件请参考 scroll-view的文档


                  ★、onPageScroll

                              参数说明

                                 属性           类型                说明

                                 scrollTop      Number             页面在垂直方向一滚动的距离(单位px)

                                 onPageScroll : function(e) { //nvue暂不支持滚动监听，可用bindingx代替
                                    console.log("滚动距离为：" + e.scrollTop);
                                  },
                                  

                              注意：

                                  onPageScroll 里不要写交互复杂的js，比如频繁修改页面。因为这个生命周期是在渲染层触发的，
                                  在非h5端，js是在逻辑层执行的，两层之间通信是由损耗的。
                                  如果在滚动过程中，频发触发两层之间的数据交换，可能会造成卡顿。

                                  在webview渲染时，比如app-vue、微信小程序、H5中，也可以使用wxs监听滚动，参考；在app-nvue中，可以使用bindingx监听滚动，参考。

                                  如果想实现滚动时标题栏透明渐变，在App和H5下，可在pages.json中配置titleNView下的type为transparent，参考。(uni-app x不支持)

                                  如果需要滚动吸顶固定某些元素，推荐使用css的粘性布局，参考插件市场。插件市场也有其他js实现的吸顶插件，但性能不佳，需要时可自行搜索。
                                  （uni-app x可自由在uts中设置固定位置）

                  ★、onBackPress
                               参数说明：

                                  属性          类型            说明

                                  from          String          触发返回定位的来源 ：
                                                                    
                                                                    'backbutton'---左上角导航栏按钮及安卓返回键；

                                                                    'navigateBack'---uni.navigateBack()方法。
                                  eg：
                                      export default {
                                        onBackPress(options) {
                                          console.log('from:' + options.from)
                                        }
                                      }

                                注意：
                                      onBackPress上不可使用async，会导致无法阻止默认返回
                                      iOS 端侧滑返回不会触发 onBackPress


                  ★、onTabItemTap

                                参数说明：

                                属性           类型           说明

                                index          Number        被点击tabItem的序号，从0开始

                                pageIndex      String        被点击tabItem 的页面路径

                                text           String        被点击tabItem的按钮文字

                                eg：
                                    onTabItemTap : function(e) {
                                        console.log(e);
                                        // e的返回格式为json对象： {"index":0,"text":"首页","pagePath":"pages/index/index"}
                                    },

                                注意：

                                     onTabItemTap常用于点击当前tabitem，滚动或刷新当前页面。如果是点击不同的tabitem，一定会触发页面切换。
                                     
                                     如果想在App端实现点击某个tabitem不跳转页面，不能使用onTabItemTap，
                                     可以使用plus.nativeObj.view放一个区块盖住原先的tabitem，并拦截点击事件。

                                     支付宝小程序平台onTabItemTap表现为点击非当前tabitem后触发，因此不能用于实现点击返回顶部这种操作


                  ★、onNavigationBarButtonTap

                              参数说明：

                                  属性       类型      说明

                                  index      Number    原生标题栏按钮数组的下标


                              eg:
                                  onNavigationBarButtonTap : function (e) {
                                      console.log(e);
                                      // e的返回格式为json对象：{"text":"测试","index":0}
                                  }

                              注意：

                                  nvue 页面weex编译模式支持的生命周期同weex，具体参考：weex生命周期介绍。
            */

    </script>
  </body>
</html>